package icu.qx.wm.service.impl;

import java.math.BigDecimal;
import java.util.List;

import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.security.utils.SecurityUtils;
import icu.qx.common.utils.CodeUtils;
import icu.qx.wm.domain.WmStorageInfo;
import icu.qx.wm.exception.ProductReceiptException;
import icu.qx.wm.mapper.WmStorageInfoMapper;
import icu.qx.wm.vo.ProWorkOrderVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import icu.qx.wm.mapper.WmProductReceiptMapper;
import icu.qx.wm.domain.WmProductReceipt;
import icu.qx.wm.service.IWmProductReceiptService;
import org.springframework.transaction.annotation.Transactional;

/**
 * 产品入库单Service业务层处理
 *
 * @author ruoyi
 * &#064;date  2024-06-17
 */
@Service
public class WmProductReceiptServiceImpl implements IWmProductReceiptService {
    private final WmProductReceiptMapper wmProductReceiptMapper;
    private final WmStorageInfoMapper wmStorageInfoMapper;
    private final CodeUtils codeUtils;

    @Autowired
    public WmProductReceiptServiceImpl(
            WmProductReceiptMapper wmProductReceiptMapper,
            WmStorageInfoMapper wmStorageInfoMapper,
            CodeUtils codeUtils
    ) {
        this.wmProductReceiptMapper = wmProductReceiptMapper;
        this.wmStorageInfoMapper = wmStorageInfoMapper;
        this.codeUtils = codeUtils;
    }

    /**
     * 查询产品入库单
     *
     * @param prCode 产品入库单主键
     * @return 产品入库单
     */
    @Override
    public WmProductReceipt selectWmProductReceiptByPrCode(String prCode) {
        return wmProductReceiptMapper.selectWmProductReceiptByPrCode(prCode);
    }

    /**
     * 查询产品入库单列表
     *
     * @param wmProductReceipt 产品入库单
     * @return 产品入库单
     */
    @Override
    public List<WmProductReceipt> selectWmProductReceiptList(WmProductReceipt wmProductReceipt) {
        return wmProductReceiptMapper.selectWmProductReceiptList(wmProductReceipt);
    }

    /**
     * 新增产品入库单
     *
     * @param wmProductReceipt 产品入库单
     * @return 结果
     */
    @Override
    public int insertWmProductReceipt(WmProductReceipt wmProductReceipt) {
        String code = codeUtils.generateCode("wm_product_receipt");
        wmProductReceipt.setPrCode(code);
        wmProductReceipt.setPrBatch(code);
        return wmProductReceiptMapper.insertWmProductReceipt(wmProductReceipt);
    }

    // 修改产品入库单
    @Override
    public int updateWmProductReceipt(WmProductReceipt wmProductReceipt) {
        wmProductReceipt.setUpdateBy(SecurityUtils.getUsername());
        wmProductReceipt.setUpdateTime(DateUtils.getNowDate());
        return wmProductReceiptMapper.updateWmProductReceipt(wmProductReceipt);
    }

    /**
     * 产品入库
     *
     * @param wmProductReceipt 产品入库单
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = ProductReceiptException.class)
    public int storeWmProductReceipt(WmProductReceipt wmProductReceipt) {
        try {
            String status = wmProductReceipt.getPrStatus();
            String pdCode = wmProductReceipt.getPrProductCode();
            String prBatch = wmProductReceipt.getPrBatch();

            if ("2".equals(status)) {
                // 产品入库
                handleProductEntry(wmProductReceipt, pdCode, prBatch);

                // 回写工单已入库
                ProWorkOrderVo workOrderVo = new ProWorkOrderVo();
                workOrderVo.setPrOrderCode(wmProductReceipt.getPrOrderCode());
                workOrderVo.setStatus("6");
                workOrderVo.setUpdateBy(SecurityUtils.getUsername());
                workOrderVo.setUpdateTime(DateUtils.getNowDate());
                int count = wmProductReceiptMapper.updateWorkOrderStatus(workOrderVo);
                if (count == 0) {
                    throw new ProductReceiptException("更新工单状态失败");
                }
            } else {
                // 撤回入库
                handleProductWithdrawal(wmProductReceipt, pdCode, prBatch);

                // 回写工单未入库
                ProWorkOrderVo workOrderVo = new ProWorkOrderVo();
                workOrderVo.setPrOrderCode(wmProductReceipt.getPrOrderCode());
                workOrderVo.setStatus("3");
                workOrderVo.setUpdateBy(SecurityUtils.getUsername());
                workOrderVo.setUpdateTime(DateUtils.getNowDate());
                int count = wmProductReceiptMapper.updateWorkOrderStatus(workOrderVo);
                if (count == 0) {
                    throw new ProductReceiptException("更新工单状态失败");
                }
            }

            int result = wmProductReceiptMapper.updateWmProductReceipt(wmProductReceipt);
            if (result == 0) {
                throw new ProductReceiptException("更新产品入库单失败");
            }
            return result;
        } catch (Exception e) {
            throw new ProductReceiptException("更新产品入库单失败: " + e.getMessage(), e);
        }
    }

    private void handleProductEntry(WmProductReceipt wmProductReceipt, String pdCode, String prBatch) {
        int count = wmStorageInfoMapper.selectWmStorageInfoCountByStPdCode(pdCode, prBatch);
        if (count > 0) {
            // 存在 库存相加
            BigDecimal oldStorage = wmStorageInfoMapper.selectWmStorageInfoStorage(pdCode, prBatch);
            BigDecimal newStorage = oldStorage.add(wmProductReceipt.getPrReceiptNum());
            updateInfoStorage(wmProductReceipt, newStorage);
        } else {
            // 不存在 直接新增
            WmStorageInfo info = setWmStorageInfo(wmProductReceipt);
            int i = wmStorageInfoMapper.insertWmStorageInfo(info);
            if (i == 0) {
                throw new ProductReceiptException("插入库存信息失败");
            }
        }
    }

    private void handleProductWithdrawal(WmProductReceipt wmProductReceipt, String pdCode, String prBatch) {
        BigDecimal oldStorage = wmStorageInfoMapper.selectWmStorageInfoStorage(pdCode, prBatch);
        BigDecimal callbackStorage = wmProductReceipt.getPrReceiptNum();
        int result = oldStorage.compareTo(callbackStorage);
        if (result == 0) {
            // 库存数量 = 撤回库存 删除
            int i = wmStorageInfoMapper.deleteWmStorageInfo(pdCode, prBatch);
            if (i == 0) {
                throw new ProductReceiptException("删除库存信息失败");
            }
        } else if (result > 0) {
            // 库存数量 > 撤回库存 相减
            BigDecimal newStorage = oldStorage.subtract(callbackStorage);
            updateInfoStorage(wmProductReceipt, newStorage);
        } else {
            throw new ProductReceiptException("撤回库存大于当前库存，操作失败");
        }
    }

    private void updateInfoStorage(WmProductReceipt wmProductReceipt, BigDecimal newStorage) {
        WmStorageInfo info = setWmStorageInfo(wmProductReceipt);
        // 更新库存
        info.setStorageInfoNum(newStorage);
        // 设置更新信息
        info.setUpdateBy(SecurityUtils.getUsername());
        info.setUpdateTime(DateUtils.getNowDate());
        info.setCreateBy(null);
        info.setCreateTime(null);
        int i = wmStorageInfoMapper.updateWmStorageInfo(info);
        if (i == 0) {
            throw new ProductReceiptException("更新库存信息失败");
        }
    }


    // 设定库存信息
    private static WmStorageInfo setWmStorageInfo(WmProductReceipt wmProductReceipt) {
        WmStorageInfo info = new WmStorageInfo();
        info.setStSlCode(wmProductReceipt.getPrStoLocation());
        info.setStPdCode(wmProductReceipt.getPrProductCode());
        info.setStorageInfoNum(wmProductReceipt.getPrReceiptNum());
        info.setStorageInfoBatch(wmProductReceipt.getPrBatch());
        info.setSiProductionDate(wmProductReceipt.getPrProductionDate());
        info.setSiExpirationDate(wmProductReceipt.getPrExpirationDate());
        info.setCreateBy(SecurityUtils.getUsername());
        info.setCreateTime(DateUtils.getNowDate());
        return info;
    }

    /**
     * 批量删除产品入库单
     *
     * @param prCodes 需要删除的产品入库单主键
     * @return 结果
     */
    @Override
    public int deleteWmProductReceiptByPrCodes(String[] prCodes) {
        return wmProductReceiptMapper.deleteWmProductReceiptByPrCodes(prCodes);
    }

    /**
     * 查询工单
     */
    @Override
    public List<ProWorkOrderVo> selectWorkOrder(ProWorkOrderVo proWorkOrderVo) {
        return wmProductReceiptMapper.selectWorkOrder(proWorkOrderVo);
    }
}
